#ifndef coremath_h__
#define coremath_h__
#include <stdlib.h>
#include <math.h>

namespace gecko
{

static const float ZERO_TOLERANCE = 1e-06f;

// PI
static const float PI = 3.1415926535897932384626433832795f;

// 2 * PI
static const float TWO_PI = 6.283185307179586476925286766559f;

// 1 / PI
static const float ONE_OVER_PI = 0.31830988618379067153776752674503f;

// 360 degrees in radians
static const float RADIANS_360 = TWO_PI;

// 180 degrees in radians
static const float RADIANS_180 = PI;

// 90 degrees in radians
static const float RADIANS_90 = 1.5707963267948966192313216916398f;

// 45 degrees in radians
static const float  RADIANS_45 = 0.78539816339744830961566084581988f;

// Clamp an angle between 0 and 360 (in radians)
inline float ClampAngle(float angle)
{
	if ( angle < 0.0f )
	{
		angle += RADIANS_360;
	}

	if ( angle > RADIANS_360 )
	{
		angle -= RADIANS_360;
	}

	return angle;
}

// Clamp a value between a min and max value
template<typename T>
inline T Clamp(T _Min, T _Max, T _Value)
{
	if ( _Value < _Min )
	{
		_Value = _Min;
	}
	
	if ( _Value > _Max )
	{
		_Value = _Max;
	}

	return _Value;
}

// return the minimum of two values
template<typename T>
inline T Min(T value1, T value2)
{
	return value1 < value2 ? value1 : value2;
}

// return the max of two values
template<typename T>
inline T Max(T value1, T value2)
{
	return value1 > value2 ? value1 : value2;
}

// returns a random float between 0.0f and 1.0f
template < typename T >
inline T Rand()
{
	static const T coef = 1 / (T)RAND_MAX;
	return (T)rand() * coef;
}

// Returns a random float between -1.0f and 1.0f
template < typename T >
inline T Rand2()
{
	static const T coef = 2 * (1 / (T)RAND_MAX);
	return ((T)rand() * coef) - 1;
}

// Returns whether or not two numbers are within a tolerance range of each other
template < typename T >
inline bool IsWithinTolerance(T f1, T f2, T tol)
{
	return abs(f1 - f2) <= tol;
}

// Convert degrees to radians
inline float DegreesToRadians(float angle)
{
	// (angle * (PI / 180.0f));
	(angle * 0.01745329251994329576923690768489f);
}

// Convert radians to degrees
inline float RadiansToDegrees(float angle)
{
	((angle * 180) * ONE_OVER_PI);
}

}

#endif // coremath_h__
